#include </usr/include/sys/io.h>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
using namespace std;
char sign='\\';//linux��������'\/' 
string sig="\\";
struct FileTree{
	string file_name;
	string file_path;
	long long  size=0;
	unordered_map<int,int64_t> chunk_handles;
	vector<int> next;
	int x,y;
	FileTree(){}
	FileTree(string f_n,string f_p,long long _size){
		file_name=f_n;
		file_path=f_p;
		size     =_size;
	}
};
class GetFiles{
private:
	int all;
	int mx;
	int change;
	int parent[1024];//ά��ÿ���ڵ�ĸ��ڵ� 
	string output[1024];
	FileTree tr[10000]; 
	vector<int> Res;//��ɾ���Ľڵ��Ǵ��ڿ���״̬�������ظ����� 
	map<string,int> mp;//����·����Tree�ڵ��Ӧ�� 
	void getFiles(string path, vector<string>& files,int now){
	    //�ļ����
	    intptr_t hFile = 0;
	    //�ļ���Ϣ������һ���洢�ļ���Ϣ�Ľṹ��
	    struct _finddata_t fileinfo;
	    string p;//�ַ��������·��
	    if(now==0) {
			tr[now].file_name=tr[now].file_path=path;
			mp[path]=now; 
			parent[now]=-1; 
		}
	    
	    if ((hFile = _findfirst(p.assign(path).append(sig+"*").c_str(), &fileinfo)) != -1){//�����ҳɹ��������
	        do{
	            //�����Ŀ¼,����֮�����ļ����ڻ����ļ��У�
	            if ((fileinfo.attrib &  _A_SUBDIR)){
	                //�ļ���������"."&&�ļ���������".."
	                //.��ʾ��ǰĿ¼
	                //..��ʾ��ǰĿ¼�ĸ�Ŀ¼
	                //�ж�ʱ�����߶�Ҫ���ԣ���Ȼ�����޵ݹ�������ȥ�ˣ�
	                if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0){
	                	tr[now].next.push_back(++all);
	                	tr[all].file_name=fileinfo.name;
	                	tr[all].file_path=p.assign(path).append(sig).append(fileinfo.name);
	                	mp[tr[all].file_path]=all;
	                	parent[all]=now;
	                	getFiles(p.assign(path).append(sig).append(fileinfo.name), files,all);
	                	//tr[now].size+=tr[all].size;
	                	//if(now==0) cout<<tr[now].size<<" "<<tr[all].size<<"\n";
	                }
	            }
	            //�������,�����б�
	            else{
	            	tr[now].next.push_back(++all);
	            	tr[all].file_name=fileinfo.name;
	            	tr[all].file_path=p.assign(path).append(sig).append(fileinfo.name);
	                tr[all].size=fileinfo.size;
	                mp[tr[all].file_path]=all;
	                parent[all]=now;
	                //tr[now].size+=tr[all].size;
					files.push_back(p.assign(path).append(sig).append(fileinfo.name));
	            }
	        } while (_findnext(hFile, &fileinfo) == 0);
	        //_findclose������������
	        _findclose(hFile);
	    }
	}
	long long count_size(int now){//������ļ��д�С����bug�� 
		for(auto nxt:tr[now].next){
			long long num=count_size(nxt);
			tr[now].size+=num;
		}
		return tr[now].size;
	}
	void write(int x,int y,const string& file_name){
		while(output[x].size()<=y+1){
				output[x]+=' ';
			}
		output[x]+=file_name;
	}
	void add_line(int bx,int ex,int y){
		for(int i=bx;i<=ex;i++){
			while(output[i].size()<=y+1){
				output[i]+=' ';
			}
			output[i][y]='|';
		}
	}
	void add_other(int x,int y,int op){
		if(op==0) output[x][y]='-';
		else output[x][y]='-';
	}
	int dfs(int now,int x,int y){//�ݹ黭���ļ�Ŀ¼�� 
		mx=max(mx,x);
		tr[now].x=x;tr[now].y=y;
		write(x,y,tr[now].file_name);
		int las=0;
		for(int i=0;i<tr[now].next.size();i++){
			int nxt=tr[now].next[i];
			
			if(tr[nxt].next.size()==0){
				if(i==tr[now].next.size()-1) add_line(x+1,mx+1+las,y+4);
				mx=dfs(nxt,mx+1+las,y+4);    
				las=0;
			}
			else{
				if(i==tr[now].next.size()-1) add_line(x+1,mx+2+las,y+4);
				mx=dfs(nxt,mx+2+las,y+4);
				las=1;
			}
		}
		for(int i=0;i<tr[now].next.size();i++){
			int nxt=tr[now].next[i];
			add_other(tr[nxt].x,y+5,(i==tr[now].next.size()-1));
		}
		return mx;
	}
	void del_file(int now){
		for(int i=0;i<tr[now].next.size();i++){
			int nxt=tr[now].next[i];
			del_file(nxt);
		}
		mp.erase(tr[now].file_path);
		Res.push_back(now);
		tr[now].next.clear();
		tr[now].file_path="";
	}
public:
	void test(){
		for(int i=0;i<=all;i++){
			if(tr[i].file_path=="") continue;
			cout<<"filename:  "<<tr[i].file_name<<"\n"; 
			cout<<"filepath:  "<<tr[i].file_path<<"\n";
			cout<<"file_size: "<<tr[i].size<<"\n\n";
		} 
	}
	void Print_Files(){//����ļ�Ŀ¼�� 
		if(change){
			for(int i=0;i<=mx;i++){
				output[i].clear();
			}
			change=mx=0;
		}
		dfs(0,1,0);
		for(int i=0;i<=mx;i++){
			cout<<output[i]<<endl;
		}
	}
	bool Get_FileMetadata(string filepath,FileTree &node){//��ȡ�ļ���Ϣ 
		if(!mp.count(filepath)) return false;
		node=tr[mp[filepath]];
		return true;
	}
	GetFiles(string filePath){//��ʼ�� 
		all=mx=change=0;
		vector<string> files;
		getFiles(filePath, files,0);
		count_size(0);
	}
	bool Exit_Path(string filepath){
		return mp.count(filepath);
	}
	bool Add_Path(string filepath,FileTree node){//���ļ�����·�� 
		string path=filepath;
		while(path.back()!=sign) {
			path.pop_back();//�������linux�����£�Ҫ�ĳ� "\/";
		}	
		while(path.back()==sign) path.pop_back();
		if(!Exit_Path(path)) return false;
		int nod=mp[path];
		tr[nod].next.push_back(++all); 
		tr[all]=node;
		parent[all]=nod;
		mp[filepath]=all;
		change=1;
	} 
	bool Del_Path(string filepath){//ɾ��·�� 
		if(!Exit_Path(filepath)) return false;
		int now=mp[filepath];
		int fa=parent[now];
		for(int i=0;i<tr[fa].next.size();i++){
			int num=tr[fa].next[i];
			if(num==now){
				swap(tr[fa].next[i],tr[fa].next.back());
				tr[fa].next.pop_back();
				break;
			} 
		}
		del_file(mp[filepath]);
		change=1;
	}
};


int main(){
    char * filePath = "D:\\VM";//�Լ�����Ŀ¼
	GetFiles *d=new GetFiles(filePath);
	d->Print_Files();//���Ŀ¼��ʽ 
	FileTree node;
	node.file_name="A";
	node.file_path="D:\\VM\\A";
	node.size=2;
	d->Add_Path("D:\\VM\\A",node);
	d->Print_Files();//���Ŀ¼��ʽ 
	d->Del_Path("D:\\VM\\node1");
	d->Print_Files();//���Ŀ¼��ʽ 
	d->Del_Path("D:\\VM\\A");
	d->Print_Files();//���Ŀ¼��ʽ 
	d->test();
}


    